﻿using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;

namespace Dotway.WPF.Effects
{
    public class PixelateEffect : ShaderEffect
    {
        #region Fields

        private static PixelShader pixelShader = new PixelShader();

        #endregion Fields
        #region Constructors

        static PixelateEffect()
        {
            pixelShader.UriSource = Global.MakePackUri("PixelateEffect.ps");
        }

        public PixelateEffect()
        {
            this.PixelShader = pixelShader;

            // Update each DependencyProperty that's registered with a shader register.  This
            // is needed to ensure the shader gets sent the proper default value.
            UpdateShaderValue(InputProperty);
            UpdateShaderValue(HorizontalBlockCountProperty);
            UpdateShaderValue(VerticalBlockCountProperty);
        }

        #endregion Constructors
        #region Properties

        public static readonly DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(PixelateEffect), 0);
        public Brush Input
        {
            get { return (Brush)GetValue(InputProperty); }
            set { SetValue(InputProperty, value); }
        }


        public static readonly DependencyProperty HorizontalBlockCountProperty = DependencyProperty.Register("HorizontalBlockCount", typeof(double), typeof(PixelateEffect), new UIPropertyMetadata(50.0, PixelShaderConstantCallback(0), CoerceHorizontalBlockCount));
        public double HorizontalBlockCount
        {
            get { return (double)GetValue(HorizontalBlockCountProperty); }
            set { SetValue(HorizontalBlockCountProperty, value); }
        }

        public static readonly DependencyProperty VerticalBlockCountProperty = DependencyProperty.Register("VerticalBlockCount", typeof(double), typeof(PixelateEffect), new UIPropertyMetadata(50.0, PixelShaderConstantCallback(1), CoerceVerticalBlockCount));
        public double VerticalBlockCount
        {
            get { return (double)GetValue(VerticalBlockCountProperty); }
            set { SetValue(VerticalBlockCountProperty, value); }
        }

        private static object CoerceHorizontalBlockCount(DependencyObject d, object value)
        {
            PixelateEffect effect = (PixelateEffect)d;
            double newSize = (double)value;

            if (newSize < 1.0)
            {
                return effect.HorizontalBlockCount;
            }

            return newSize;
        }

        private static object CoerceVerticalBlockCount(DependencyObject d, object value)
        {
            PixelateEffect effect = (PixelateEffect)d;
            double newSize = (double)value;

            if (newSize < 1.0)
            {
                return effect.VerticalBlockCount;
            }

            return newSize;
        }   

        #endregion Properties       
    }
}
